package config

import (
	"fmt"
	"github.com/fsnotify/fsnotify"
	"github.com/spf13/viper"
	"os"
)

// LoadConfiguration 负责加载配置文件并监听热更新，返回配置结构与可能的错误
func LoadConfiguration() (Configuration, error) {
	var cfg Configuration

	// 1. 确定配置文件路径
	cfgPath := getConfigFilePath()
	if cfgPath == "" {
		return cfg, fmt.Errorf("config file path is empty")
	}

	// 2. 初始化 Viper
	v := viper.New()
	v.SetConfigFile(cfgPath)
	v.SetConfigType("yaml")

	// 3. 读取配置
	if err := v.ReadInConfig(); err != nil {
		return cfg, fmt.Errorf("failed to read config file '%s': %w", cfgPath, err)
	}

	// 4. 解析配置到结构体
	if err := v.Unmarshal(&cfg); err != nil {
		return cfg, fmt.Errorf("failed to unmarshal config: %w", err)
	}

	// 5. 监听配置热更新
	if err := watchConfig(v, &cfg); err != nil {
		return cfg, fmt.Errorf("failed to watch config: %w", err)
	}

	return cfg, nil
}

// getConfigFilePath 优先从环境变量读取配置文件路径，默认为 config.yaml
func getConfigFilePath() string {
	if customCfg := os.Getenv("VIPER_CONFIG"); customCfg != "" {
		return customCfg
	}
	return "config.yaml" // 默认值
}

// watchConfig 监听配置文件变化并自动热更新配置结构体
func watchConfig(v *viper.Viper, cfg *Configuration) error {
	v.WatchConfig()

	v.OnConfigChange(func(e fsnotify.Event) {
		fmt.Printf("[CONFIG] 🔁 Config file changed: %s\n", e.Name)

		var newCfg Configuration
		if err := v.Unmarshal(&newCfg); err != nil {
			fmt.Printf("[CONFIG] ❌ Failed to unmarshal updated config: %v\n", err)
			return
		}

		*cfg = newCfg // 原子替换配置（简单场景，生产可用 sync.Mutex 保护）

		fmt.Printf("[CONFIG] ✅ Config reloaded: %+v\n", newCfg)
	})

	return nil
}
